﻿//  -------------------- iSharePoint -------------------- //
// 
//  Company:	IT Complex, LLC
//  Project:	Smart.Common
//  File name:	CamlQueryBuilderItemGroup.cs
//  Developer:	Solomatov Igor
//  Created:	15.04.2012
// 
//  -------------------- iSharePoint -------------------- //

using System.Collections.Generic;
using System.Linq;

namespace Smart.Common.Entities
{
	/// <summary>
	/// Query item group
	/// </summary>
	public abstract class CamlQueryBuilderItemGroup<TExecutorType> : CamlQueryBuilderItem<TExecutorType>
		where TExecutorType : class
	{
		/// <summary>
		/// Children
		/// </summary>
		public List<CamlQueryBuilderItem<TExecutorType>> Children { get; set; }

		/// <summary>
		/// QueryBuilder Query Items group
		/// </summary>
		/// <param name="op">Group Operator</param>
		protected CamlQueryBuilderItemGroup(string op)
			: base(op)
		{
			Children = new List<CamlQueryBuilderItem<TExecutorType>>();
		}

		/// <summary>
		/// QueryBuilder Query Items group
		/// </summary>
		/// <param name="op">Group Operator</param>
		/// <param name="items">Items</param>
		protected CamlQueryBuilderItemGroup(string op, IEnumerable<CamlQueryBuilderItem<TExecutorType>> items)
			: base(op)
		{
			Children = new List<CamlQueryBuilderItem<TExecutorType>>(items);
		}

		/// <summary>
		/// Create new group
		/// </summary>
		public abstract CamlQueryBuilderItemGroup<TExecutorType> Create();

		/// <summary>
		/// Add child items and update their props
		/// </summary>
		/// <param name="items"></param>
		public void AddItems(IEnumerable<CamlQueryBuilderItem<TExecutorType>> items)
		{
			Children.AddRange(items);

			SetChildrenProps();
		}

		/// <summary>
		/// Add item
		/// </summary>
		public void AddItem(CamlQueryBuilderItem<TExecutorType> builderItem)
		{
			builderItem.Query = Query;
			builderItem.Group = this;

			Children.Add(builderItem);
		}

		public List<IQueryBuilderItem<TExecutorType>> FindRecursive(string op)
		{
			var res = new List<IQueryBuilderItem<TExecutorType>>();

			foreach (var item in Children)
			{
				if (item.Op.EqIC(op))
				{
					res.Add(item);
					continue;
				}

				var group = item as CamlQueryBuilderItemGroup<TExecutorType>;

				if (group != null)
					res.AddRange(group.FindRecursive(op));
			}

			return res;
		}

		/// <summary>
		/// Set for all Children QueryBuilder and Group properties
		/// </summary>
		public void SetChildrenProps()
		{
			foreach (var item in Children)
			{
				item.Query = Query;
				item.Group = this;
			}
		}

		/// <summary>
		/// Set for all Children QueryBuilder and Group properties
		/// </summary>
		public void SetChildrenProps(IEnumerable<CamlQueryBuilderItem<TExecutorType>> childrenEnumerable)
		{
			foreach (var item in childrenEnumerable)
			{
				item.Query = Query;
				item.Group = this;
			}
		}

		/// <summary>
		/// Return Cache key
		/// </summary>
		public virtual string GetCacheKey()
		{
			return GetCacheCode().ToStringX();
		}

		/// <summary>
		/// Return Cache code
		/// </summary>
		public override int GetCacheCode()
		{
			var res = Op.GetHashCode() ^ Children.Count.GetHashCode();

			return Children.Aggregate(res, (current, child) => current ^ child.GetCacheCode());
		}

		#region IList<CAMLQueryItem> members (old code)

		/*
		/// <summary>
		/// Find index of item
		/// </summary>
		public int IndexOf(QueryBuilderItem builderItem)
		{
			return Children.IndexOf(builderItem);
		}

		/// <summary>
		/// Find item at zero-based index
		/// </summary>
		public void Insert(int index, QueryBuilderItem builderItem)
		{
			builderItem.QueryBuilder = QueryBuilder;
			builderItem.Group = this;

			Children.Insert(index, builderItem);
		}

		/// <summary>
		/// Remove item at index
		/// </summary>
		public void RemoveAt(int index)
		{
			Children.RemoveAt(index);
		}

		/// <summary>
		/// Get or Set item by index
		/// </summary>
		public QueryBuilderItem this[int index]
		{
			get
			{
				return Children[index];
			}
			set
			{
				value.QueryBuilder = QueryBuilder;
				value.Group = this;

				Children[index] = value;
			}
		}

		/// <summary>
		/// Add item
		/// </summary>
		public void Add(QueryBuilderItem builderItem)
		{
			builderItem.QueryBuilder = QueryBuilder;
			builderItem.Group = this;

			Children.Add(builderItem);
		}

		/// <summary>
		/// Remove all items
		/// </summary>
		public void Clear()
		{
			Children.Clear();
		}

		/// <summary>
		/// Check whether list contains item
		/// </summary>
		public bool Contains(QueryBuilderItem builderItem)
		{
			return Children.Contains(builderItem);
		}

		/// <summary>
		/// Copy items to array
		/// </summary>
		public void CopyTo(QueryBuilderItem[] array, int arrayIndex)
		{
			Children.CopyTo(array, arrayIndex);
		}

		/// <summary>
		/// Return item count
		/// </summary>
		public int Count
		{
			get { return Children.Count; }
		}

		/// <summary>
		/// Return whether list is readonly
		/// </summary>
		public bool IsReadOnly
		{
			get { return false; }
		}

		/// <summary>
		/// Remove item
		/// </summary>
		public bool Remove(QueryBuilderItem builderItem)
		{
			return Children.Remove(builderItem);
		}

		/// <summary>
		/// Get all items
		/// </summary>
		public IEnumerator<QueryBuilderItem> GetEnumerator()
		{
			return GetEnumerator();
		}

		/// <summary>
		/// Get all items
		/// </summary>
		System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
		{
			return Children.GetEnumerator();
		}
		 */

		#endregion
	}
}